package com.wlyuan.open.scanner.repository.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wlyuan.open.scanner.constant.Constants;
import com.wlyuan.open.scanner.dao.entity.GoodsDO;
import com.wlyuan.open.scanner.dao.entity.GoodsTypeDO;
import com.wlyuan.open.scanner.dao.entity.OrderGoodsDO;
import com.wlyuan.open.scanner.dao.entity.PriceUnitDO;
import com.wlyuan.open.scanner.dao.mapper.*;
import com.wlyuan.open.scanner.domain.order.OrderGoods;
import com.wlyuan.open.scanner.domain.order.OrderGoodsConvert;
import com.wlyuan.open.scanner.repository.GoodsRepository;
import com.wlyuan.open.scanner.repository.OrderGoodsRepository;
import com.wlyuan.open.scanner.utils.enums.InvalidEnum;
import com.wlyuan.open.utils.LongUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author lijing
 * @description
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class OrderGoodsRepositoryImpl implements OrderGoodsRepository {
    private final OrderGoodsMapper orderGoodsMapper;
    private final OrderGoodsKidsKingMapper orderGoodsKidsKingMapper;
    private final GoodsMapper goodsMapper;
    private final GoodsTypeMapper goodsTypeMapper;
    private final PriceUnitMapper priceUnitMapper;
    private final GoodsRepository goodsRepository;

    @Override
    public List<OrderGoods> getByOrderId(Long orderId, Long tenantId) {
        return Optional.ofNullable(orderId).map(order -> {
            var list = getOrderGoodsList(order, tenantId);
            return OrderGoodsConvert.convert(list, tenantId);
        }).orElse(null);
    }

    private List<OrderGoodsDO> getOrderGoodsList(Long orderId, Long tenantId) {
        //订单物品信息
        List<OrderGoodsDO> list = new ArrayList<>();
        if (Constants.KING_TENANT.equals(tenantId)) {
            //订单可能属于孩子王，孩子王订单物品信息
            var kidKing = getOrderGoodsKidKing(orderId);
            Optional.ofNullable(kidKing).ifPresent(k -> {
                list.add(k);
            });
        } else {
            list.addAll(getOrderGoods(orderId));
        }
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        process(list);
        return list;
    }

    private List<OrderGoodsDO> getOrderGoods(Long orderId) {
        LambdaQueryWrapper<OrderGoodsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderGoodsDO::getGoodslstInvalid, InvalidEnum.ENABLE.getValue()).eq(OrderGoodsDO::getGoodslstOrderid, orderId);
        return orderGoodsMapper.selectList(queryWrapper);
    }

    private OrderGoodsDO getOrderGoodsKidKing(Long orderId) {
        var orderGoodsKidsKingDO = orderGoodsKidsKingMapper.getByOrderId(orderId);
        if (orderGoodsKidsKingDO == null) {
            return null;
        }
        OrderGoodsDO data = new OrderGoodsDO();
        BeanUtils.copyProperties(orderGoodsKidsKingDO, data);
        return data;
    }

    private void process(List<OrderGoodsDO> list) {
        //checkGoodsUnique(list);
        list.forEach(data -> changeGoods(data));
    }

    private void changeGoods(OrderGoodsDO data) {
        var goods = goodsRepository.getById(data.getGoodslstGoodsid());
        if (Optional.ofNullable(goods).isPresent()) {
            data.setUnit(goods.getUnit());
            data.setGoodslstName(goods.getName());
            data.setGoodsTypeId(goods.getGoodsTypeId());
            data.setGoodsTypeName(goods.getType());
            data.setChineseName(goods.getEnName());
            if (StringUtils.isBlank(data.getGoodslstBarcode())) {
                data.setGoodslstSpc(goods.getSpec());
                data.setGoodslstSingleprice(goods.getValue());
                data.setGoodslstSinglevolume(goods.getVolume());
                data.setGoodslstSingleweight(goods.getNetWeight());
                data.setGoodslstBarcode(goods.getBarcode());
            }
            if (!LongUtils.notNullDecimal(data.getGoodslstSingleprice())) {
                data.setGoodslstSingleprice(goods.getValue());
            }
            if (!LongUtils.notNullDecimal(data.getGoodslstSinglevolume())) {
                data.setGoodslstSinglevolume(goods.getVolume());
            }
            if (!LongUtils.notNullDecimal(data.getGoodslstSingleweight())) {
                data.setGoodslstSingleweight(goods.getNetWeight());
            }
        } else {
            data.setUnit("其他");
            data.setGoodsTypeName("其他");
        }
        if (StringUtils.isBlank(data.getGoodslstSpc())) {
            data.setGoodslstSpc("#");
        }
    }

    private GoodsDO getGoodsById(Long goodsId) {
        return Optional.ofNullable(goodsId).map(id -> {
            QueryWrapper<GoodsDO> query = new QueryWrapper<>();
            query.lambda().eq(GoodsDO::getGoodsId, id);
            return goodsMapper.selectOne(query);
        }).orElse(null);
    }

    public GoodsTypeDO getGoodsType(Long typeId) {
        return Optional.ofNullable(typeId).map(t -> {
            QueryWrapper<GoodsTypeDO> query = new QueryWrapper<>();
            query.lambda().eq(GoodsTypeDO::getGoodstypeId, t)
                    .eq(GoodsTypeDO::getGoodstypeInvalid, InvalidEnum.ENABLE.getValue()).isNotNull(GoodsTypeDO::getGoodstypeName);
            return goodsTypeMapper.selectOne(query);
        }).orElse(null);
    }

    public PriceUnitDO getUnit(Long unitId) {
        return Optional.ofNullable(unitId).map(t -> {
            QueryWrapper<PriceUnitDO> query = new QueryWrapper<>();
            query.lambda().eq(PriceUnitDO::getUnitId, t)
                    .eq(PriceUnitDO::getUnitInvalid, InvalidEnum.ENABLE.getValue()).isNotNull(PriceUnitDO::getUnitName);
            return priceUnitMapper.selectOne(query);
        }).orElse(null);
    }

    private void checkGoodsUnique(List<OrderGoodsDO> goodsList) {
        List<String> goodsKeys = new ArrayList<>();
        goodsList.forEach(g -> {
            goodsKeys.add(buildKey(g));
        });

        goodsKeys.stream().distinct();
        for (int i = 0; i < goodsKeys.size(); i++) {
            String goodsKey = goodsKeys.get(i);
            var list = goodsList.stream().filter(g -> buildKey(g).equals(goodsKey)).collect(Collectors.toList());
            if (list.size() > 1) {
                for (int j = 0; j < list.size(); j++) {
                    var goods = list.get(j);
                    goods.setGoodslstBatchno(goods.getGoodslstBatchno() + "-#" + j);
                }
            }
        }
    }

    private String buildKey(OrderGoodsDO goods) {
        return goods.getGoodslstOrderid() + "#" + goods.getGoodslstGoodsid() + "#" + goods.getGoodslstBatchno();
    }
}
